//**********************************************************************
//	Programmer	-	Sujal Bista
//	File Name	-	GraphicsGL.h
//	Description	:	
//					API handler for openGL
//**********************************************************************

#ifndef _GRAPHICS_GL_H_
#define _GRAPHICS_GL_H_ 

#include "graphicsBase.h"
#include "picture.h"

#include "CL\opencl.h"
#include "glew.h"
#include "wglew.h"

class graphicsGL:public graphicsBase
{
		//form related variables
		HWND hWnd;						// handle to main window
		HDC hDC;						// handle to main device context
		
	public:
		
		//class to handle input layout for vertex
		class inputLayoutGL:public inputLayoutBase
		{
			public:
				unsigned int data;	// vertex array object
				inputElementDesc *desc;
				unsigned int descCount;

				//constructor
				inputLayoutGL(void)
				{
					desc=NULL;
					descCount=NULL;
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(desc)
					{
						delete[] desc;
						desc=NULL;
						descCount=NULL;
					}

					if(data)
					{
						glDeleteVertexArrays(1,&data);
						data=NULL;
					}
				}

				//destructor
				~inputLayoutGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle raw shader data
		class blobGL:public blobBase
		{
			public:
				char *data;
				char *fileName;

				//constructor
				blobGL(void)
				{
					data=NULL;
					fileName=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						delete[] data;
						data=NULL;
					}

					if(fileName)
					{
						delete []fileName;
						fileName=NULL;
					}
				}

				//destructor
				~blobGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to device
		class deviceGL:public deviceBase
		{
			public:
				HDC data;						//handle to main device context
				cl_platform_id clPlatformID;    // openCL platform
				cl_device_id clDeviceID;        // openCL device
				cl_context clContext;			// openCL context
				
				//constructor
				deviceGL(void):deviceBase()
				{
					data=NULL;
					clPlatformID=NULL;    // openCL platform
					clDeviceID=NULL;        // openCL device
					clContext=NULL;			// openCL context
				}

				//create deferred context
				bool createDeferredContext(deviceContextBase* dcData);

			private:

				//checks the shaders status
				bool checkShaderCreationStatusGL(const graphicsDefinitions::SHADER_TYPE &sType,blobGL &shRawDataGL, unsigned int shaderIDGL);
			
			public:

				//creates vertex shader
				bool createVertexShader(blobBase* shRawData,shaderVertexBase* shData);
				//creates hull shader
				bool createHullShader(blobBase* shRawData,shaderHullBase* shData);
				//creates domain shader
				bool createDomainShader(blobBase* shRawData,shaderDomainBase* shData);
				//creates geometry shader
				bool createGeometryShader(blobBase* shRawData,shaderGeometryBase* shData);
				//creates pixel shader
				bool createPixelShader(blobBase* shRawData,shaderPixelBase* shData);
				//creates compute shader
				bool createComputeShader(blobBase* shRawData,shaderComputeBase* shData);


				//creates input layout
				bool createInputLayout(inputElementDesc *inputDesc, unsigned int inputDescCount,blobBase *shData,inputLayoutBase *inLayData);
		
				//creates buffer in gpu
				bool createBuffer(bufferDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, bufferBase *bData);
				//creates 1D texture
				bool createTexture1D(texture1DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture1DBase *tData);
				//creates 2D texture
				bool createTexture2D(texture2DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture2DBase *tData);
				//creates 3D texture
				bool createTexture3D(texture3DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture3DBase *tData);
		
				//creates shader resource view from file
				bool createShaderResourceViewFromFile(char* fileName, shaderResourceViewBase * srvData);
				//creates shader resource view. param0, param1, param2, param3 depends on the dimension type. Please refer to dx version for params
				bool createShaderResourceView(resourceBase *bData, graphicsDefinitions::DATA_FORMAT format, graphicsDefinitions::SRV_DIMENSION dimension, unsigned int param0, unsigned int param1, unsigned int param2, unsigned int param3,shaderResourceViewBase* srvData);
				//creates unordered access view. param0, param1, param2 depends on the dimension type. Please refer to dx version for params
				bool createUnorderedAccessView(resourceBase *bData, graphicsDefinitions::DATA_FORMAT format, graphicsDefinitions::UAV_DIMENSION dimension, unsigned int param0, unsigned int param1, unsigned int param2, unorderedAccessViewBase* uavData);
				
				//creates sampler state
				bool createSamplerState(graphicsDefinitions::FILTER filter,	graphicsDefinitions::TEXTURE_ADDRESS_MODE addMode[3], float mipLODBias, unsigned int maxAnisotropy, graphicsDefinitions::COMPARISON_FUNC comparisonFunc, float borderColor[4], float minLOD, float maxLOD, samplerStateBase *ssBase);
		
				//creates rasterizer state
				bool createRasterizerState(graphicsDefinitions::FILL_MODE fillMode,graphicsDefinitions::CULL_MODE cullMode,bool frontCounterClockwise,int depthBias,float depthBiasClamp,float slopeScaledDepthBias,bool depthClipEnable, bool scissorEnable, bool multisampleEnable, bool antialiasedLineEnable,	rasterizerStateBase *rsData);

				//creates a blend state
				bool createBlendState(const blendDesc *bStateDesc,blendStateBase *bStateData);

				//clears the device
				void clear(void)
				{
					if(data)
					{
						//make current rendering context null
						wglMakeCurrent(data, NULL);
						data=NULL;
					}

					if(clContext)
					{
						clReleaseContext(clContext);
						clContext=NULL;
					}
				}

				//destructor
				~deviceGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle immediate Contex
		class deviceContextGL:public deviceContextBase
		{
			public:
				HGLRC data;
				unsigned int shaderObject;	//current shader Object
				unsigned int attachedShaders[graphicsDefinitions::SHADER_TYPE_END];	//list of attached shader
				cl_kernel  attachedComputeShader;	//opencl kernel binded

				inputLayoutGL* vertexLayout; //current vertex layout
				unsigned int drawMode;	//current draw mode
				unsigned int indexDataType; //data type of index
				cl_command_queue clCommandQueue;// openCL command que
				
				//constructor
				deviceContextGL(void):deviceContextBase()
				{
					data=NULL;
					shaderObject=0;
					memset(attachedShaders,0,sizeof(unsigned int)*((int)graphicsDefinitions::SHADER_TYPE_END));
					vertexLayout=NULL;
					drawMode=GL_TRIANGLES;
					indexDataType=GL_UNSIGNED_INT;
					clCommandQueue=NULL;// openCL command que
					attachedComputeShader=NULL;
				}

				//resizes the output screen
				bool resize(const unsigned int &_width,const unsigned int &_height);

				//Restore all default settings of the device context
				void clearState(void);

				//create a command list and record command
				bool finishCommandList(bool restoreDeferredContextState, commandListBase* clData);
				//queues command from command list to the device
				void executeCommandList(commandListBase* clData, bool restoreContextState);

				//sets input layout
				void setInputLayout(inputLayoutBase *inLayData);
				
				//updates sub resource
				void updateSubResource(resourceBase *destinationBuffer, unsigned int destinationSubresource, const box *destinationBox, const void *sourceData, unsigned int sourceRowPitch, unsigned int sourceDepthPitch);
				//copies one buffer to another
				void copyResource(resourceBase *dest, resourceBase *src);
				//maps the data
				void *map(resourceBase *bData, unsigned int subresource, graphicsDefinitions::MAP mapType,unsigned int &rowPitch, unsigned int &depthPitch);
				//unmap the data
				void unmap(resourceBase *bData, unsigned int subresource);

				//sets vertex buffer
				void setVertexBuffers(unsigned int startSlot,unsigned int bufferCount, bufferBase *bufferDatas,unsigned int strides,unsigned int offsets);
				//sets index buffer
				void setIndexBuffer(bufferBase *bufferData,graphicsDefinitions::DATA_FORMAT format, unsigned int offset);

				//sets primitive topology
				void setPrimitiveTopology(graphicsDefinitions::PRIMITIVE_TOPOLOGY topology);

				//Draw non-indexed, non-instanced primitives
				void draw(unsigned int vertexCount,unsigned int startVertexLocation);
				//draw indexed primitive
				void drawIndexed(unsigned int indexCount,unsigned int startIndexLocation,int baseVertexLocation);
				//Draw non-indexed, instanced primitives.
				void drawInstanced(unsigned int vertexCountPerInstance,unsigned int instanceCount,unsigned int startVertexLocation,unsigned int startInstanceLocation);
				//Draw indexed, instanced primitives.
				void drawIndexedInstanced(unsigned int indexCountPerInstance,unsigned int instanceCount,unsigned int startIndexLocation,int baseVertexLocation,unsigned int startInstanceLocation);
				//Draw instanced, GPU-generated primitives.
				void drawInstancedIndirect(bufferBase *pBufferForArgs,unsigned int alignedByteOffsetForArgs);
				//Draw indexed, instanced, GPU-generated primitives.
				void drawIndexedInstancedIndirect(bufferBase *pBufferForArgs,unsigned int alignedByteOffsetForArgs);
				
				//clear the render target
				void clearRenderTargetView(renderTargetViewBase *rTargetView, float *clearColor);

				//Clears the depth-stencil resource
				void clearDepthStencilView(depthStencilViewBase *dStencilView,unsigned int clearFlags, float depth, unsigned int stencil);

				//set constant buffer in vertex shader
				void VSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);
				//set constant buffer in hull shader
				void HSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);
				//set constant buffer in domain shader
				void DSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);
				//set constant buffer in geometry shader
				void GSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);
				//set constant buffer in pixel shader
				void PSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);
				//set constant buffer in compute shader
				void CSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex);

				//set shader resources in vertex shader
				void VSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set shader resources in hull shader
				void HSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set shader resources in domain shader
				void DSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set shader resources in geometry shader
				void GSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set shader resources in pixel shader
				void PSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set shader resources in compute shader
				void CSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex);
				//set unordered access view in compute shader
				void CSSetUnorderedAccessViews(unsigned int startSlot,unsigned int numUAVs, unorderedAccessViewBase *uavResources,unsigned int *initialCounts);

				//set sampler in vertex shader
				void VSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);
				//set sampler in hull shader
				void HSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);
				//set sampler in domain shader
				void DSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);
				//set sampler in geometry shader
				void GSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);
				//set sampler in pixel shader
				void PSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);
				//set sampler in compute shader
				void CSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers);

				//set vertex shader
				void VSSetShader(shaderVertexBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);
				//set hull shader
				void HSSetShader(shaderHullBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);
				//set domain shader
				void DSSetShader(shaderDomainBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);
				//set geometry shader
				void GSSetShader(shaderGeometryBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);
				//set pixel shader
				void PSSetShader(shaderPixelBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);
				//set compute shader
				void CSSetShader(shaderComputeBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances);

			private:

				//checks the shaders status
				bool checkShaderLinkStatusGL(unsigned int shaderObjectIDGL);

			public:

				//called after all the shaders are set before drawing
				void shaderBegin(void);
				//called after all the drawing is done
				void shaderEnd(void);
				//returns uniform block index. only used in opengl
				unsigned int getUniformBlockIndex(char *name);
				//returns uniform location. only used in opengl
				unsigned int getUniformLocation(char *name);

				//sets rasterizer state
				void RSSetState(rasterizerStateBase *rsData);


				//execute direct compute command list from a thread group
				void dispatch(unsigned int threadGroupCountX, unsigned int threadGroupCountY, unsigned int threadGroupCountZ);
		


				//clears the deviceContext
				void clear(void)
				{
					
					for(unsigned int i=0;i<((int)graphicsDefinitions::SHADER_TYPE_END);i++)
					{
						if(attachedShaders[i])
							glDetachShader(shaderObject, attachedShaders[i]);
					}

					if(shaderObject)
					{
						glDeleteProgram(shaderObject);
						shaderObject=NULL;
					}

					if(data)
					{
						wglDeleteContext(data);
						data=NULL;
					}

					vertexLayout=NULL;

					if(clCommandQueue)
					{
						clReleaseCommandQueue(clCommandQueue);
						clCommandQueue=NULL;
					}
				}

				//destructor
				~deviceContextGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle buffer
		class bufferGL:public bufferBase
		{
			public:
				enum BUFFER_TYPE
				{
					BUFFER_TYPE_CL,
					BUFFER_TYPE_CPU,
					BUFFER_TYPE_GL
				};

				cl_mem clBuffer;
				char *cpuBuffer;
				unsigned int glBuffer;	//buffer ID
				BUFFER_TYPE bufferType;	//buffer ID
				unsigned int target;	//target type
				unsigned int usage;		//usage type
				unsigned int size;		//size of the buffer in bytes
				
				//constructor
				bufferGL(void):bufferBase()
				{
					clBuffer=NULL;
					cpuBuffer=NULL;
					glBuffer=NULL;


					target=NULL;
					usage=NULL;
					size=NULL;
					bufferType=BUFFER_TYPE_GL;
				}

				//returns the type
				graphicsDefinitions::RESOURCE_DIMENSION getType(void)
				{
					return graphicsDefinitions::RESOURCE_DIMENSION_BUFFER;
				}

				//clears the buffer
				void clear(void)
				{
					if(glBuffer)
					{
						glDeleteBuffers(1,&glBuffer);
						glBuffer=NULL;
					}
					if(clBuffer)
					{
						clReleaseMemObject(clBuffer);
						clBuffer=NULL;
					}
					if(cpuBuffer)
					{
						delete[] cpuBuffer;
						cpuBuffer=NULL;
					}
					target=NULL;
					usage=NULL;
					size=NULL;
				}

				//destructor
				~bufferGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle 1D texture
		class texture1DGL:public texture1DBase
		{
			public:
				unsigned int data;	//id

				//constructor
				texture1DGL(void):texture1DBase()
				{
					data=NULL;
				}

				//returns the type
				graphicsDefinitions::RESOURCE_DIMENSION getType(void)
				{
					return graphicsDefinitions::RESOURCE_DIMENSION_TEXTURE1D;
				}

				//clears the texture1D
				void clear(void)
				{
					if(data)
					{
						glDeleteTextures(1,&data);
						data=NULL;
					}
				}

				//destructor
				~texture1DGL()
				{
					//clears the texture1D
					clear();
				}
		};

		//class to handle 2D texture
		class texture2DGL:public texture2DBase
		{
			public:
				unsigned int data;	//id
				unsigned int textureTarget; //resource target eg. GL_TEXTURE_2D
				unsigned int internalFormat;
				unsigned int format;
				unsigned int dataType;

				//constructor
				texture2DGL(void):texture2DBase()
				{
					data=NULL;
					textureTarget=NULL;
					internalFormat=NULL;
					format=NULL;
					dataType=NULL;
				}

				//returns the type
				graphicsDefinitions::RESOURCE_DIMENSION getType(void)
				{
					return graphicsDefinitions::RESOURCE_DIMENSION_TEXTURE2D;
				}

				//clears the texture2D
				void clear(void)
				{
					if(data)
					{
						glDeleteTextures(1,&data);
						data=NULL;
						textureTarget=NULL;
						internalFormat=NULL;
						format=NULL;
						dataType=NULL;
					}
				}

				//destructor
				~texture2DGL()
				{
					//clears the texture2D
					clear();
				}
		};

		//class to handle 3D texture
		class texture3DGL:public texture3DBase
		{
			public:
				unsigned int data;	//id

				//constructor
				texture3DGL(void):texture3DBase()
				{
					data=NULL;
				}
								
				//returns the type
				graphicsDefinitions::RESOURCE_DIMENSION getType(void)
				{
					return graphicsDefinitions::RESOURCE_DIMENSION_TEXTURE3D;
				}

				//clears the texture3D
				void clear(void)
				{
					if(data)
					{
						glDeleteTextures(1,&data);
						data=NULL;
					}
				}

				//destructor
				~texture3DGL()
				{
					//clears the texture3D
					clear();
				}
		};

				
		//render target view
		class  renderTargetViewGL:public renderTargetViewBase
		{
			public:
				void *data;

				//constructor
				renderTargetViewGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						data=NULL;
					}
				}

				//destructor
				~renderTargetViewGL()
				{
					//clears the buffer
					clear();
				}
		};
		//depth stencil view
		class depthStencilViewGL:public depthStencilViewBase
		{
			public:
				void *data;

				//constructor
				depthStencilViewGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						data=NULL;
					}
				}

				//destructor
				~depthStencilViewGL()
				{
					//clears the buffer
					clear();
				}
		};
		//shader resource view
		class shaderResourceViewGL:public shaderResourceViewBase
		{
			public:
				//unsigned int data;	//id
				//unsigned int textureTarget; //resource target eg. GL_TEXTURE_2D
				resourceBase *resourcePtr;
				bool freeResource;
				//unsigned int internalFormat;
				//unsigned int format;
				//unsigned int dataType;
				
				//constructor
				shaderResourceViewGL(void)
				{
					//data=NULL;
					//textureTarget=NULL;
					resourcePtr=NULL;
					freeResource=true;
					//internalFormat=NULL;
					//format=NULL;
					//dataType=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(freeResource)
						delete resourcePtr;	
					resourcePtr=NULL;

					//if(data)
					//{
						//glDeleteTextures(1,&data);
						//data=NULL;
						//textureTarget=NULL;
						//resourcePtr=NULL;
						//internalFormat=NULL;
						//format=NULL;
						//dataType=NULL;
					//}
				}

				//destructor
				~shaderResourceViewGL()
				{
					//clears the buffer
					clear();
				}
		};
		//shader resource view
		class unorderedAccessViewGL:public unorderedAccessViewBase
		{
			public:
				void *data;
				resourceBase *resourcePtr;

				//constructor
				unorderedAccessViewGL(void)
				{
					data=NULL;
					resourcePtr=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						data=NULL;
						resourcePtr=NULL;
					}
				}

				//destructor
				~unorderedAccessViewGL()
				{
					//clears the buffer
					clear();
				}
		};
		

		//class to handle vertex shader data
		class shaderVertexGL:public shaderVertexBase
		{
			public:
				unsigned int data;

				//constructor
				shaderVertexGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteShader(data);
						data=NULL;
					}
				}

				//destructor
				~shaderVertexGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle hull shader data
		class shaderHullGL:public shaderHullBase
		{
			public:
				unsigned int data;

				//constructor
				shaderHullGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteShader(data);
						data=NULL;
					}
				}

				//destructor
				~shaderHullGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle domain shader data
		class shaderDomainGL:public shaderDomainBase
		{
			public:
				unsigned int data;

				//constructor
				shaderDomainGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteShader(data);
						data=NULL;
					}
				}

				//destructor
				~shaderDomainGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle geometry shader data
		class shaderGeometryGL:public shaderGeometryBase
		{
			public:
				unsigned int data;

				//constructor
				shaderGeometryGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteShader(data);
						data=NULL;
					}
				}

				//destructor
				~shaderGeometryGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle pixel shader data
		class shaderPixelGL:public shaderPixelBase
		{
			public:
				unsigned int data;

				//constructor
				shaderPixelGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteShader(data);
						data=NULL;
					}
				}

				//destructor
				~shaderPixelGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class to handle compute shader data
		class shaderComputeGL:public shaderComputeBase
		{
			public:
				cl_program data;	//opencl program
				cl_kernel clKernel;  //opencl kernel

				//constructor
				shaderComputeGL(void)
				{
					data=NULL;
					clKernel=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						clReleaseProgram(data);
						data=NULL;
					}
					if(clKernel)
					{
						clReleaseKernel(clKernel);
						clKernel=NULL;
					}
				}

				//destructor
				~shaderComputeGL()
				{
					//clears the buffer
					clear();
				}
		};
		
		//sampler state
		class samplerStateGL:public samplerStateBase
		{
			public:
				unsigned int data;	//sampler data

				//constructor
				samplerStateGL(void)
				{
					data=NULL;					
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						glDeleteSamplers(1,&data);
						data=NULL;
					}					
				}

				//destructor
				~samplerStateGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class instance for shader
		class classInstanceGL:public classInstanceBase
		{
			public:
				void *data;

				//constructor
				classInstanceGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						data=NULL;
					}
				}

				//destructor
				~classInstanceGL()
				{
					//clears the buffer
					clear();
				}
		};

		//class for Rasterizer State
		class rasterizerStateGL:public rasterizerStateBase
		{
			public:
				graphicsDefinitions::FILL_MODE fillMode;
				graphicsDefinitions::CULL_MODE cullMode;
				bool frontCounterClockwise;
				int depthBias;
				float depthBiasClamp;
				float slopeScaledDepthBias;
				bool depthClipEnable;
				bool scissorEnable;
				bool multisampleEnable;
				bool antialiasedLineEnable;

				//constructor
				rasterizerStateGL(void)
				{
					
				}

				//clears the buffer
				void clear(void)
				{					
				}

				//destructor
				~rasterizerStateGL()
				{
					//clears the buffer
					clear();
				}
		};

		//command list
		class commandListGL:public commandListBase
		{
			public:
				void *data;

				//constructor
				commandListGL(void)
				{
					data=NULL;
				}

				//clears the buffer
				void clear(void)
				{
					if(data)
					{
						delete[] data;
						data=NULL;
					}
				}

				//destructor
				~commandListGL()
				{
					//clears the buffer
					clear();
				}
		};
	
	private:

		//loads shader text file
		char* readFile(char *fileName);

	public:

		//constructor
		graphicsGL(void);
		
		//initilizes the device
		bool init(deviceBase *gDevice, deviceContextBase *dContext, texture2DBase *renderTarget, texture2DBase *depthStencil,renderTargetViewBase *rTargetView,depthStencilViewBase *dStencilView);

		//closes the device
		bool close(void);

		//resizes the output screen
		bool resize(deviceBase *gDevice, deviceContextBase *dContext, texture2DBase *renderTarget, texture2DBase *depthStencil,renderTargetViewBase *rTargetView,depthStencilViewBase *dStencilView, const unsigned int &_width,const unsigned int &_height);

		//swaps back and front buffer
		inline void swapBuffer(void);

		//sets vsync option
		inline void setVerticalSync(bool option);

		//checks for any error
		inline bool checkError(void);
		
		//destructor
		~graphicsGL();

		//compiles shader for the file
		bool compileShaderFromFile(char* fileName,char *entryPoint, char *shaderModel, blobBase* shData);

		//sets window handler
		void setWindowHandler(const HWND &_hWnd);

		//returns window handle
		inline HWND& getWindowHandler(void){return hWnd;};
			
};

#endif